package vip.xiaonuo.pay.modular.alipay.service.impl;

import cn.hutool.core.lang.Console;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConstants;
import com.alipay.api.diagnosis.DiagnosisUtils;
import com.alipay.api.domain.*;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import vip.xiaonuo.dev.api.DevConfigApi;
import vip.xiaonuo.pay.modular.alipay.entity.AliPayRecord;
import vip.xiaonuo.pay.modular.alipay.enums.AliPayTradeStatusEnums;
import vip.xiaonuo.pay.modular.alipay.service.IAliPayService;
import vip.xiaonuo.pay.modular.alipay.utils.ParamsToBeanUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

@Service
public class AliPayServiceImpl implements IAliPayService {

    /**
     * 应用ID,收款账号就是appId对应的支付宝账号

     */
    private static final String SYS_PAY_ALI_APP_ID = "SYS_PAY_ALI_APP_ID";
    /**
     * 商户PID，卖家支付宝账号Id

     */
    private static final String SYS_PAY_ALI_SELLER_ID = "SYS_PAY_ALI_SELLER_ID";
    /**
     * 商户私钥，RSA2私钥

     */
    private static final String SYS_PAY_ALI_MERCHANT_PRIVATE_KEY = "SYS_PAY_ALI_MERCHANT_PRIVATE_KEY";
    /**
     * 支付宝公钥

     */
    private static final String SYS_PAY_ALI_PUBLIC_KEY = "SYS_PAY_ALI_PUBLIC_KEY";
    /**
     * 接口内容加密密钥，对称密钥

     */
    private static final String SYS_PAY_ALI_CONTENT_KEY = "SYS_PAY_ALI_CONTENT_KEY";
    /**
     * 页面跳转同步通知页面

     */
    private static final String SYS_PAY_ALI_RETURN_URL = "SYS_PAY_ALI_RETURN_URL";
    /**
     * 服务器异步通知页面路径

     */
    private static final String SYS_PAY_ALI_NOTIFY_URL = "SYS_PAY_ALI_NOTIFY_URL";


    @Resource
    private AlipayClient alipayClient;

    @Resource
    private DevConfigApi devConfigApi;

    /**
     * app统一收单下单并支付页面接口的调用
     * 支付宝开发平台接受 request 请求对象后
     * 会为开发者生成一个html 形式的form表单，包含自动提交的脚本
     *
     * @param model
     * @return
     * @
     */
    @Override
    @SneakyThrows(value = AlipayApiException.class)
    public String tradeAppPay(AlipayTradeAppPayModel model) {

        String returnUrl = devConfigApi.getValueByKey(SYS_PAY_ALI_RETURN_URL); // 同步通知回调地址
        String notifyUrl = devConfigApi.getValueByKey(SYS_PAY_ALI_NOTIFY_URL); // 异步通知回调地址

        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();

        // 同步通知页面
        request.setReturnUrl(returnUrl);

        // 异步回调页面
        request.setNotifyUrl(notifyUrl);

        request.setBizModel(model);

        AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);

        if (response.isSuccess()) { // 调用支付成功

            return response.getBody();

        } else { // 调用支付失败

            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
            String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);

            Console.error("调用支付失败，diagnosisUrl = " + diagnosisUrl);

            return response.getSubMsg();
        }
    }

    /**
     * 网页统一收单下单并支付页面接口的调用
     * 支付宝开发平台接受 request 请求对象后
     * 会为开发者生成一个html 形式的form表单，包含自动提交的脚本
     *
     * @param model
     * @return
     * @
     */
    @Override
    @SneakyThrows(value = AlipayApiException.class)
    public String tradePagePay(AlipayTradePagePayModel model) {

        String returnUrl = devConfigApi.getValueByKey(SYS_PAY_ALI_RETURN_URL); // 同步通知回调地址
        String notifyUrl = devConfigApi.getValueByKey(SYS_PAY_ALI_NOTIFY_URL); // 异步通知回调地址

        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();

        // 必选，产品码。 商家和支付宝签约的产品码。 枚举值（点击查看签约情况）： FAST_INSTANT_TRADE_PAY：新快捷即时到账产品。 注：目前仅支持FAST_INSTANT_TRADE_PAY
        model.setProductCode("FAST_INSTANT_TRADE_PAY");

        // 同步通知页面
        request.setReturnUrl(returnUrl);

        // 异步回调页面
        request.setNotifyUrl(notifyUrl);

        request.setBizModel(model);

        AlipayTradePagePayResponse response = alipayClient.pageExecute(request);

        if (response.isSuccess()) { // 调用支付成功

            return response.getBody();

        } else { // 调用支付失败

            return response.getSubMsg();

        }
    }

    /**
     * 同步通知回调
     *
     * @param request
     * @return
     */
    @Override
    @SneakyThrows(value = AlipayApiException.class)
    public boolean handleReturn(HttpServletRequest request) {

        String alipayPublicKey = devConfigApi.getValueByKey(SYS_PAY_ALI_PUBLIC_KEY); // 支付宝公钥

        // 解析回调参数
        Map<String, String> params = new HashMap<>();
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String paramName = parameterNames.nextElement();
            String paramValue = request.getParameter(paramName);
            params.put(paramName, paramValue);
        }

        // 验证签名（使用支付宝公钥）
        boolean signatureVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey,
                AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2);

        if (signatureVerified) { // 签名验证通过

            // 处理支付结果
            String tradeStatus = params.get("trade_status");
            if (AliPayTradeStatusEnums.TRADE_SUCCESS.getValue().equals(tradeStatus)
                    || AliPayTradeStatusEnums.TRADE_FINISHED.getValue().equals(tradeStatus)) {
                // 支付成功，更新订单状态等操作
                return true;
            } else {
                // 支付失败，处理异常情况
                Console.log("支付失败 !");
            }
        } else { // 签名验证不通过，可能是伪造的通知

            // 不应进行后续处理，可以记录日志进行排查
            Console.log("签名验证失败 !");
        }
        return false;
    }

    /**
     * 异步通知回调
     *
     * @param params
     * @return
     */
    @Override
    @SneakyThrows(value = AlipayApiException.class)
    public boolean handleNotify(Map<String, String> params) {

        String alipayPublicKey = devConfigApi.getValueByKey(SYS_PAY_ALI_PUBLIC_KEY); // 支付宝公钥

        // 验证签名（使用支付宝公钥）
        boolean signatureVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey,
                AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2);

        if (signatureVerified) { // 签名验证通过

            // 回调参数转实体类
            AliPayRecord payRecord = ParamsToBeanUtils.payParamsToBean(params);

            // 处理支付结果
            String tradeStatus = payRecord.getTradeStatus();

            // 商户订单号
            String outTradeNo = payRecord.getOutTradeNo();
            boolean save = true;

            if (AliPayTradeStatusEnums.TRADE_SUCCESS.getValue().equals(tradeStatus)) { // 交易成功

                Console.log("交易成功 !" + params);

            } else if (AliPayTradeStatusEnums.TRADE_FINISHED.getValue().equals(tradeStatus)) { // 交易关闭

                Console.log("交易关闭 !" + params);

            } else if (AliPayTradeStatusEnums.TRADE_CLOSED.getValue().equals(tradeStatus)) { // 未支付交易超时关闭，或支付完成后全额退款
                Console.log("未支付交易超时关闭，或支付完成后全额退款 !" + params);

            } else { // 支付失败，处理异常情况
                Console.log("支付失败 !" + params);

            }

            return save;
        } else { // 签名验证不通过，可能是伪造的通知

            // 不应进行后续处理，可以记录日志进行排查
            Console.log("签名验证失败 !");
        }
        return false;
    }

    /**
     * 统一退费接口
     *
     * @param model
     * @return
     */
    @Override
    @SneakyThrows(value = AlipayApiException.class)
    public String tradeRefund(AlipayTradeRefundModel model) {

        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();

        request.setBizModel(model);
        AlipayTradeRefundResponse response = alipayClient.execute(request);

        if (response.isSuccess()) { // 调用成功

            String outTradeNo = response.getOutTradeNo(); // 商户支付订单号
            String refundFee = response.getRefundFee(); // 退款金额

            Console.log(" outTradeNo ====> " + outTradeNo);
            Console.log(" refundFee ====> " + refundFee);

            return response.getMsg();
        } else { // 调用失败
            return response.getSubMsg();
        }
    }

    /**
     * 统一查单接口
     *
     * @param model
     * @return
     */
    @Override
    @SneakyThrows(value = AlipayApiException.class)
    public String tradeQuery(AlipayTradeQueryModel model) {

        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizModel(model);
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        System.out.println(response.getBody());
        if (response.isSuccess()) {
            return response.getMsg();
        } else {
            return response.getSubMsg();
        }
    }

    /**
     * 统一关单接口
     *
     * @param model
     * @return
     */
    @Override
    @SneakyThrows(value = AlipayApiException.class)
    public String tradeClose(AlipayTradeCloseModel model) {

        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
        request.setBizModel(model);
        AlipayTradeCloseResponse response = alipayClient.execute(request);

        if (response.isSuccess()) {
            return response.getMsg();
        } else {

            return response.getSubMsg();
        }
    }

    /**
     * 统一收单交易退款查询
     *
     * @param model
     * @return
     */
    @Override
    @SneakyThrows(value = AlipayApiException.class)
    public String tradeFastPayRefundQuery(AlipayTradeFastpayRefundQueryModel model) {

        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();

        request.setBizModel(model);
        AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
        System.out.println(response.getBody());
        if (response.isSuccess()) {
            return response.getMsg();
        } else {
            return response.getSubMsg();
        }
    }


}
